package onetotwenty;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;

public class ProjectSeventeen {
	private Map<Integer, Integer> dictionary = new HashMap<Integer, Integer>();

	@Before
	public void before() {
		dictionary.put(1, 3); // one
		dictionary.put(2, 3); // two
		dictionary.put(3, 5); // three
		dictionary.put(4, 4); // four
		dictionary.put(5, 4); // five
		dictionary.put(6, 3); // six
		dictionary.put(7, 5); // seven
		dictionary.put(8, 5); // eight
		dictionary.put(9, 4); // nine
		dictionary.put(10, 3); // ten
		dictionary.put(11, 6); // eleven
		dictionary.put(12, 6); // twelve
		dictionary.put(13, 8); // thirteen
		dictionary.put(14, 8); // fourteen
		dictionary.put(15, 7); // fifteen
		dictionary.put(16, 7); // sixteen
		dictionary.put(17, 9); // seventeen
		dictionary.put(18, 8); // eighteen
		dictionary.put(19, 8); // nineteen
		dictionary.put(20, 6); // twenty
		dictionary.put(30, 6); // thirty
		dictionary.put(40, 5); // forty
		dictionary.put(50, 5); // fifty
		dictionary.put(60, 5); // sixty
		dictionary.put(70, 7); // seventy
		dictionary.put(80, 6); // eighty
		dictionary.put(90, 6); // ninety
		dictionary.put(100, 7); // hundred
	}

	public int getNumberLessThan1000(int n) {
		int item = 0;

		if (n == 1000) {
			return 11;
		}

		if (n >= 100) {
			item += dictionary.get(n / 100);
			item += dictionary.get(100);
			n %= 100;

			if (n != 0) {
				item += 3;
			}
		}

		if (n >= 20) {
			item += dictionary.get((n / 10) * 10);
			n %= 10;
		} else if (n >= 10) {
			for (int i = 19; i >= 10; i--) {
				if (n - i < 10) {
					item += dictionary.get(n);
					n -= i;
					break;
				}
			}
		}

		if (n < 10 && n >= 1) {
			item += dictionary.get(n);
		}

		return item;
	}

	public int getNumbers(int start, int end) {
		int item = 0;
		for (int i = start; i <= end; i++) {
			item += getNumberLessThan1000(i);
		}
		return item;
	}

	@Test
	public void testSimple() {
		System.out.println(getNumberLessThan1000(100));
	}

	@Test
	public void test1to9() {
		assertThat(getNumbers(1, 9), is(36));
		assertThat(getNumbers(10, 19), is(70));
		assertThat(getNumbers(20, 99), is(748));
		assertThat(getNumbers(100, 999), is(20259));
	}

	@Test
	public void answer() {
		assertThat(getNumbers(1, 1000), is(21124));
	}
}
